// 将 require 改为 import
import juice from 'juice';
import { JSDOM } from 'jsdom';
import MarkdownIt from 'markdown-it';
import hljs from 'highlight.js';
import { basicStyle } from './styles.js';
import { markdownThemes, codeThemes } from '../themes/index.js';
import markdownUrlAddSpan from './markdown-it-urlspan.js';
import markdownItSpan from './markdown-it-span.js';
import markdownItTableContainer from './markdown-it-table-container.js';
import markdownItMath from './markdown-it-math.js';
import markdownItLinkfoot from './markdown-it-linkfoot.js';
import markdownItTableOfContents from 'markdown-it-table-of-contents';
import markdownItRuby from 'markdown-it-ruby';
import markdownItImplicitFigures from 'markdown-it-implicit-figures';
import markdownItDeflist from 'markdown-it-deflist';
import markdownItLiReplacer from './markdown-it-li.js';
import markdownItImageFlow from './markdown-it-imageflow.js';
import markdownItImsize from 'markdown-it-imsize';

// Constants
const LAYOUT_ID = 'nice';
const BOX_ID = 'nice-rich-text-box';
const MJX_DATA_FORMULA = 'data-formula';

// Helper function to create a DOM environment
function createDOM(htmlContent) {
    const fullHtml = `<!DOCTYPE html><html><body><div id="${LAYOUT_ID}"><div id="${BOX_ID}">${htmlContent}</div></div></body></html>`;
    const dom = new JSDOM(fullHtml);
    return dom.window.document;
}

// --- Platform-specific Math Conversion Functions ---

const solveWeChatMath = (document) => {
    const layout = document.getElementById(LAYOUT_ID);
    if (!layout) return;
    const mjxs = layout.getElementsByTagName('mjx-container');
    for (let i = 0; i < mjxs.length; i++) {
        const mjx = mjxs[i];
        if (!mjx.hasAttribute('jax')) {
            continue;
        }

        mjx.removeAttribute('jax');
        mjx.removeAttribute('display');
        mjx.removeAttribute('tabindex');
        mjx.removeAttribute('ctxtmenu_counter');
        const svg = mjx.firstChild;
        if (svg && svg.nodeName === 'svg' && svg.getAttribute) {
            const width = svg.getAttribute('width');
            const height = svg.getAttribute('height');
            svg.removeAttribute('width');
            svg.removeAttribute('height');
            if (width) svg.style.width = width;
            if (height) svg.style.height = height;
        }
    }
};

const solveZhihuMath = (document) => {
    const layout = document.getElementById(LAYOUT_ID);
    if (!layout) return;
    const mjxs = layout.getElementsByTagName('mjx-container');
    for (let i = mjxs.length - 1; i >= 0; i--) {
        const mjx = mjxs[i];
        let data = mjx.getAttribute(MJX_DATA_FORMULA);
        if (!data) {
            continue;
        }

        if (mjx.hasAttribute('display') && data.indexOf('\\tag') === -1) {
            data += '\\\\'; // Double backslash for Node.js string context
        }

        const img = document.createElement('img');
        img.className = 'Formula-image';
        img.setAttribute('data-eeimg', 'true');
        img.src = '';
        img.alt = data;
        mjx.replaceWith(img);
    }
};

const solveJuejinMath = (document) => {
    const layout = document.getElementById(LAYOUT_ID);
    if (!layout) return;
    const mjxs = layout.getElementsByTagName('mjx-container');
    for (let i = mjxs.length - 1; i >= 0; i--) {
        const mjx = mjxs[i];
        const data = mjx.getAttribute(MJX_DATA_FORMULA);
        if (!data) {
            continue;
        }

        const encodedData = encodeURIComponent(data);
        let replacementHTML;
        const altText = data.replace(/"/g, '&quot;');

        if (mjx.hasAttribute('display')) { // Block equation
            replacementHTML = `<figure><img class="equation" src="https://juejin.im/equation?tex=${encodedData}" alt="${altText}"/></figure>`;
        } else { // Inline equation
            replacementHTML = `<span><img style="display:inline;" class="equation" src="https://juejin.im/equation?tex=${encodedData}" alt="${altText}"/></span>`;
        }

        const tempContainer = document.createElement('div');
        tempContainer.innerHTML = replacementHTML;
        mjx.replaceWith(...tempContainer.childNodes);
    }
};

// Juejin specific code block handling
const solveJuejinCode = (html) => {
    return html.replace(/<pre([^>]*)class="custom"([^>]*)>(.*?)<\/pre>/gs, (match, preAttrs, _, content) => {
        const newContent = content
            .replace(/display: -webkit-box;/g, "display: block;")
            .replace(/<br\s*\/?>/gi, "\n<span/>")
            .replace(/&nbsp;/g, " ");
        return `<pre${preAttrs}class="custom"${_}>${newContent}</pre>`;
    });
};

// General HTML processing and style inlining
const solveHtml = (htmlContent, markdownTheme, codeTheme) => {
    let html = htmlContent;
    // String replacements for compatibility
    html = html.replace(/<mjx-container (class="inline.+?)<\/mjx-container>/g, "<span $1</span>");
    html = html.replace(/\s<span class="inline/g, '&nbsp;<span class="inline');
    html = html.replace(/svg><\/span>\s/g, "svg></span>&nbsp;");
    html = html.replace(/mjx-container/g, "section");
    html = html.replace(/class="mjx-solid"/g, 'fill="none" stroke-width="70"');
    html = html.replace(/<mjx-assistive-mml.*?<\/mjx-assistive-mml>/gs, "");

    // Combine styles
    const selectedMarkdownStyle = markdownThemes[markdownTheme] || markdownThemes.normal;
    const selectedCodeStyle = codeThemes[codeTheme] || codeThemes.github; // <-- 正确获取 codeTheme
    const combinedStyle = selectedCodeStyle + basicStyle + selectedMarkdownStyle; // <-- 拼接样式

    let res = '';
    try {
        res = juice.inlineContent(html, combinedStyle, { // <-- 使用 juice 内联样式
            inlinePseudoElements: true,
            preserveImportant: true,
        });
    } catch (e) {
        console.error("Error during CSS inlining:", e);
        return html; // Return HTML without inlined styles on error
    }
    return res;
};

// Date formatting utility
export const dateFormat = (date, fmt) => {
  var o = {
    "M+": date.getMonth() + 1, // 月份
    "d+": date.getDate(), // 日
    "h+": date.getHours(), // 小时
    "m+": date.getMinutes(), // 分
    "s+": date.getSeconds(), // 秒
    "q+": Math.floor((date.getMonth() + 3) / 3), // 季度
    S: date.getMilliseconds(), // 毫秒
  };
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) {
      fmt = fmt.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
      );
    }
  }
  return fmt;
};

// Word count utility
export const wordCalc = (str) => {
  if (!str) return 0;
  str = str.replace(/\s+/g, '');
  str = str.replace(/[\uFF00-\uFFEF]/g, '');
  str = str.replace(/[\u3000-\u303F]/g, '');
  str = str.replace(/[\u2000-\u206F]/g, '');
  str = str.replace(/[\u25A0-\u25FF]/g, '');
  str = str.replace(/[\u0000-\u007F]/g, '');
  return str.length;
};

// --- Main Conversion Function ---

async function convertMarkdown(markdown, platform, markdownTheme = 'normal', codeTheme = 'github') {
    // 1. Convert Markdown to initial HTML
    const md = new MarkdownIt({
      html: true,
      highlight: function (str, lang) {
        if (lang && hljs.getLanguage(lang)) {
          try {
            return '<pre class="custom"><code class="hljs">' +
                   hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
                   '</code></pre>';
          } catch (__) {}
        }
        return '<pre class="custom"><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
      }
    })
    .use(markdownUrlAddSpan)
    .use(markdownItSpan)
    .use(markdownItTableContainer)
    .use(markdownItMath)
    .use(markdownItLinkfoot)
    .use(markdownItTableOfContents, {
      transformLink: () => "",
      includeLevel: [2, 3],
      markerPattern: /^\[toc\]/im,
    })
    .use(markdownItRuby)
    .use(markdownItImplicitFigures, {figcaption: true})
    .use(markdownItDeflist)
    .use(markdownItLiReplacer)
    .use(markdownItImageFlow)
    .use(markdownItImsize);
    let rawHtml = md.render(markdown); // Use a different variable for the initial render

    // 2. Create a JSDOM environment
    const document = createDOM(rawHtml); // Pass the initial render to createDOM
    const boxElement = document.getElementById(BOX_ID);

    let htmlToProcess; // Variable to hold the HTML string for styling

    // Check if the main content box exists
    if (!boxElement) {
        console.error(`Element with ID ${BOX_ID} not found in initial HTML. Proceeding with raw HTML.`);
        // Wrap raw HTML if boxElement is missing, assuming it should still be styled
        // Ensure the raw HTML is also wrapped in a structure that juice can process with styles
         // Note: If rawHtml already contains <pre><code>, this might wrap it again.
         // Consider if rawHtml needs the same <pre class="custom"><code class="hljs"> structure
         // if highlighting wasn't applied initially. For simplicity, we wrap the whole rawHtml.
        htmlToProcess = `<div id="${LAYOUT_ID}">${rawHtml}</div>`;
    } else {
         // 3. Apply platform-specific DOM transformations
        switch (platform) {
            case 'wechat':
                solveWeChatMath(document);
                break;
            case 'zhihu':
                solveZhihuMath(document);
                break;
            case 'juejin':
                solveJuejinMath(document);
                break;
        }
        // Get the HTML content *after* potential DOM modifications
        const innerHtml = boxElement.innerHTML;
        // Re-wrap the inner HTML with the necessary parent structure for juice
        htmlToProcess = `<div id="${LAYOUT_ID}">${innerHtml}</div>`;
    }

    // 4. Apply platform-specific STRING transformations (if any)
    if (platform === 'juejin') {
        // Apply Juejin code fix on the *wrapped* HTML before styling
        htmlToProcess = solveJuejinCode(htmlToProcess);
    }

    // 5. Apply general HTML solving and inline styles
    const finalHtml = solveHtml(htmlToProcess, markdownTheme, codeTheme);

    return finalHtml;
}

// Export the main function
export { convertMarkdown };